﻿using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.WebUtilities;

namespace VK.TransportClient.Curl
{
    public class CurlHttpClient : ITransportClient
    {
        protected const string HEADER_UPLOAD_CONTENT_TYPE = "Content-Type: multipart/form-data";
        protected const string QUESTION_MARK = "?";

        protected Dictionary<string, object> initial_opts;
        private readonly HttpClient _client;

        private enum CurlOpt
        {
            HEADER = 42,
            CONNECTTIMEOUT = 78,
            RETURNTRANSFER = 19913,
        }
        
        public CurlHttpClient(int connection_timeout, HttpMessageHandler? handler = null) {
            initial_opts = new Dictionary<string, object>() {
            //    { CurlOpt.HEADER         , true},
            //    { CurlOpt.CONNECTTIMEOUT , $connection_timeout},
            //    { CurlOpt.RETURNTRANSFER , true},
            };
            _client = handler is null ? new HttpClient() : new HttpClient(handler);
        }
            
        public Task<TransportClientResponse> PostAsync(string url, HttpContent payload = null)
        {
            return SendRequest(url, content: payload, method: HttpMethod.Post);
        }

        public Task<TransportClientResponse> GetAsync(string url, Dictionary<string, string> payload = default)
        {
            return SendRequest(QueryHelpers.AddQueryString(url, payload), method: HttpMethod.Get);
        }

        public Task<TransportClientResponse> UploadAsync(string url, string parameterName, string path)
        {
            throw new System.NotImplementedException();
        }
        
        public async Task<TransportClientResponse> SendRequest(string url, Dictionary<string, object> opts = null, HttpContent content = null, HttpMethod method = null) {

            var request = new HttpRequestMessage(method ?? HttpMethod.Get, url) {Content = content};
            if (opts != null)
                foreach (var (key, value) in opts)
                {
                    request.Headers.Add(key, value.ToString());
                }

            foreach (var (key, value) in initial_opts)
            {
                request.Headers.Add(key, value.ToString());
            }

            var response = await _client.SendAsync(request);

            var http_status = (int)response.StatusCode;
        
            if (!response.IsSuccessStatusCode) {
                var error_msg = $"Failed curl request. Curl error {http_status}";
                // if ($curl_error) {
                //     $error_msg .= ": {$curl_error}";
                // }

                error_msg += '.';

                throw new TransportRequestException(error_msg);
            }
            
            return parseRawResponse(http_status, response);
        }
        
        protected TransportClientResponse parseRawResponse(int http_status, HttpResponseMessage response) {
            return new TransportClientResponse(http_status, response.Headers, response.Content);
        }
    }
}